import { MyBtn } from "./MyBtn";

// react 组件生命周期
// 组件的生命周期  (https://segmentfault.com/a/1190000016617400?utm_source=tag-newest)
/*
 react 组件的生命周期
 含义   组件从初始化渲染到被移除或者销毁的过程  成为组件的生命周期

 1. 每个组件都有生命周期
 2. react 通过组件的生命周期钩子函数来管理 组件
 3. 系统 某些状态和参数发生改变的时候，系统立马去通知 对应处理的函数叫做钩子函数
 hooks 钩子函数  允许在特定的时期添加用户自己的代码  不同的阶段添加自己的逻辑代码

 react 组件的生命周期 分为三个阶段 
 1.mount  组件的初始化  从虚拟DOM 渲染成为真实DOM 的过程    1  
 2.update   组件的数据变化 setState  组件的state 更新 导致二次渲染的过程     n  
 3.unmount  组件销毁   组件因为路由切换而销毁 (浏览器的垃圾回收机制 )     1  

 mounted 组件载入阶段  (钩子函数)

 0.constructor   构造器函数  
 1.getDefaultProps   设置组件默认的props   废弃 16已经被废弃   App.defaultPorps 
 2.getInitialState   设置组件默认的state   废弃 16已经被废弃   this.state state = {}
 3.componentWillMount  在jsx被渲染到页面之前被调用  废弃 16尚存  17马上废弃 警告 
 3.1  getDerivedStateFromProps ( 组件每次被rerender的时候，包括在组件构建之后(虚拟dom之后，实际dom挂载之前)，每次获取新的props或state之后；;每次接收新的props之后都会返回一个对象作为新的state，返回null则说明不需要更新state)   17新增的 
 4.render   渲染函数是react中默认的函数  虚拟DOM 渲染成真实DOM 
 5.componentDidMount   jsx被渲染到页面后被调用   1 

*/ 
/*
update 组件数据更新阶段   组件修改 state  组件接收的props发送改变  都会进入 update 阶段 
1. componentWillReceiveProps(nextProps)  接收变化的props   废弃 16尚存  17马上废弃  警告  
2.1 getDerivedStateFromProps  获取最新的props 和 state 
2. shouldComponentUpdate  询问是否更新  true 更新 false 不更新   性能优化  
3. componentWillUpdate ==>     组件即将更新之前    废弃 16尚存  17马上废弃   警告
4. render   组件开始二次渲染  update  
4.1 getSnapshotBeforeUpdate  组件更新之前触发 得到旧的props 和 state  17新增 
5. componentDidUpdate   组件更新渲染数据完毕 

*/ 
// 组件销毁移除 路由切换 
// componentDidCatch    捕获异常 
// componentWillUnmount  这个函数几乎不会使用到，因为浏览器本身具有垃圾回收机制


export class LifeTime  extends Component{
  state = {
     word:"I am so happy",
     num:2107,
     flag :true 
  }
  changeWord=(e)=>{
    this.setState({
      word:e.target.value 
    })
  }
  changeCount=()=>{
    this.setState({
      num:++this.state.num
    })
  }

  componentDidMount(){
    console.log("componentDidMount - 父组件载入完毕")
  }
  render(){
    const {
      word,num ,flag 
    } = this.state; 
    return (
      <div>
        <h2> React 组件生命周期 (V15 V16 V17) </h2>
        <p>
          <input type="text" value={word} onChange={this.changeWord}/>
        </p>
        <p>
          num === {num }
        </p>
        <MyBtn text={'changeCount'} onClick={this.changeCount}/>
        <MyBtn text={'销毁组件'} onClick={()=>this.setState({flag:!flag})}/>
        <p>
          组件载入 -  组件数据更新  - 组件销毁 
        </p>
        <hr/>
        {
          flag && <ChildOne
          num={num}
          word={word}
        ></ChildOne>
        }
      </div>
    )
  }
} 

var index = 0;
class ChildOne extends Component{
  state = {
    count:1000,
    text:"ARe you OK?"
  }

  changeCount=()=>{
    this.setState({
      count:++this.state.count 
    })
  }

  log=(msg)=>{
    console.log(`## ${++index} ----- ${msg}`)
  }

  constructor(){
    super()
    this.log("constructor - 组件的构造器")
  }

  // componentWillMount(){
  //   this.log("componentWillMount  虚拟DOM 即将被渲染成真实DOM")
  // }

  // componentWillReceiveProps(nextProps,nextState){
  //   this.log("componentWillReceiveProps - 接收变化的props")
  //   console.log(nextProps)
  // }
 
  shouldComponentUpdate(nextProps,nextState){
    this.log("shouldComponentUpdate  - 询问是否更新")
    // 性能优化  询问是否更新
    // console.log(nextProps)
    // console.log(this.props)
    // if(nextProps.word !=  this.props.word){
    //   return true ;
    // }else{
    //   return false 
    // }
    return true;
  }
  // componentWillUpdate(){
  //   this.log("componentWillUpdate  - 组件即将更新之前")
  // }
  render(){
    this.log("render - 正在渲染DOM")
    const {
      word,num 
    } = this.props
    const {
      count 
    } = this.state 
    return (
      <div>
        <h2> 子组件 -  1 - childone </h2>
        <p>props--- {num} -- {word}</p>
        <h2>count -- {count}</h2>
        <p>
          <MyBtn text={'change'} onClick={this.changeCount}></MyBtn>
        </p>
      </div>
    )
  }
  // 获取最新的state 
  static getDerivedStateFromProps(nextState){
    console.log(nextState);
    console.log("## "+(++index)+" -  getDerivedStateFromProps")
    return {

    }
  }
  getSnapshotBeforeUpdate(prevProps,prevState){
    this.log("getSnapshotBeforeUpdate - 更新之前触发 获取state和props")
    console.log(prevProps,prevState)
    return {
      prevProps,
      prevState
    }  // 这个数据会返回给  componentDidUpdate
  }
  componentDidMount(){
    this.log("componentDidMount - 子组件已经载入 成为真实DOM")
    // ajax
    // 插件实例化  Swiper  
  }

  componentDidUpdate(){
    this.log("componentDidUpdate -- 组件二次更新完毕")
  }

  componentWillUnmount(){
    // 清除计数器
    // 路由切换
    // 组件切换
    this.log("componentWillUnmount -- 组件被销毁")
  }
}

// __proto__  prototype     
// 构造函数 
// 构造器
// 原型属性   prototype
// 静态属性  没有this 

// 1. React16新的生命周期弃用了componentWillMount、componentWillReceiveProps，componentWillUpdate
// 2. 新增了getDerivedStateFromProps、getSnapshotBeforeUpdate来代替弃用的三个钩子函数（componentWillMount、componentWillReceiveProps，componentWillUpdate）
// 3. React16并没有删除这三个钩子函数，但是不能和新增的钩子函数（getDerivedStateFromProps、getSnapshotBeforeUpdate）混用，React17将会删除componentWillMount、componentWillReceiveProps，componentWillUpdate
// 4. 新增了对错误的处理（componentDidCatch）